﻿using SmallJob.Model;
using SmallShop.Services.Code;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Mail;
using System.Security.Cryptography;
using System.Text.RegularExpressions;

namespace SmallJob.Services.Code
{
    public class UserUtility
    {
        // Encrypt a byte array into a byte array using a key and an IV
        public static byte[] Encrypt(byte[] clearData, byte[] Key, byte[] IV)
        {
            MemoryStream ms = new MemoryStream();
            Rijndael alg = Rijndael.Create();
            alg.Key = Key;
            alg.IV = IV;
            CryptoStream cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write);

            cs.Write(clearData, 0, clearData.Length);

            cs.Close();
            byte[] encryptedData = ms.ToArray();

            return encryptedData;
        }

        // Encrypt a string into a string using a password
        //    Uses Encrypt(byte[], byte[], byte[])
        public static string Encrypt(string password, string username)
        {
            // First we need to turn the input string into a byte array.

            byte[] clearBytes = System.Text.Encoding.Unicode.GetBytes(password);

            PasswordDeriveBytes pdb = new PasswordDeriveBytes(username, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });

            byte[] encryptedData = Encrypt(clearBytes, pdb.GetBytes(32), pdb.GetBytes(16));
            return Convert.ToBase64String(encryptedData);
        }

        public static byte[] Encrypt(byte[] clearData, string Password)
        {
            PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });

            return Encrypt(clearData, pdb.GetBytes(32), pdb.GetBytes(16));
        }

        // Encrypt a file into another file using a password
        public static void Encrypt(string fileIn, string fileOut, string Password)
        {
            // First we are going to open the file streams
            FileStream fsIn = new FileStream(fileIn, FileMode.Open, FileAccess.Read);
            FileStream fsOut = new FileStream(fileOut, FileMode.OpenOrCreate, FileAccess.Write);

            // Then we are going to derive a Key and an IV from the Password and create an algorithm
            PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });

            Rijndael alg = Rijndael.Create();
            alg.Key = pdb.GetBytes(32);
            alg.IV = pdb.GetBytes(16);

            CryptoStream cs = new CryptoStream(fsOut, alg.CreateEncryptor(), CryptoStreamMode.Write);

            int bufferLen = 4096;
            byte[] buffer = new byte[bufferLen];
            int bytesRead;

            do
            {
                // read a chunk of data from the input file
                bytesRead = fsIn.Read(buffer, 0, bufferLen);

                // encrypt it
                cs.Write(buffer, 0, bytesRead);
            } while (bytesRead != 0);

            // close everything
            cs.Close(); // this will also close the unrelying fsOut stream
            fsIn.Close();
        }

        // Decrypt a byte array into a byte array using a key and an IV
        public static byte[] Decrypt(byte[] cipherData, byte[] Key, byte[] IV)
        {
            // Create a MemoryStream that is going to accept the decrypted bytes
            MemoryStream ms = new MemoryStream();

            Rijndael alg = Rijndael.Create();

            alg.Key = Key;
            alg.IV = IV;

            CryptoStream cs = new CryptoStream(ms, alg.CreateDecryptor(), CryptoStreamMode.Write);

            cs.Write(cipherData, 0, cipherData.Length);

            cs.Close();

            byte[] decryptedData = ms.ToArray();

            return decryptedData;
        }

        public static string Decrypt(string password, string username)
        {
            byte[] cipherBytes = Convert.FromBase64String(password);

            PasswordDeriveBytes pdb = new PasswordDeriveBytes(username, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });

            byte[] decryptedData = Decrypt(cipherBytes, pdb.GetBytes(32), pdb.GetBytes(16));

            return System.Text.Encoding.Unicode.GetString(decryptedData);
        }

        public static byte[] Decrypt(byte[] cipherData, string Password)
        {
            PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });

            return Decrypt(cipherData, pdb.GetBytes(32), pdb.GetBytes(16));
        }

        // Decrypt a file into another file using a password
        public static void Decrypt(string fileIn, string fileOut, string Password)
        {
            // First we are going to open the file streams
            FileStream fsIn = new FileStream(fileIn, FileMode.Open, FileAccess.Read);
            FileStream fsOut = new FileStream(fileOut, FileMode.OpenOrCreate, FileAccess.Write);

            // Then we are going to derive a Key and an IV from the Password and create an algorithm
            PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
            Rijndael alg = Rijndael.Create();
            alg.Key = pdb.GetBytes(32);
            alg.IV = pdb.GetBytes(16);

            CryptoStream cs = new CryptoStream(fsOut, alg.CreateDecryptor(), CryptoStreamMode.Write);

            int bufferLen = 4096;
            byte[] buffer = new byte[bufferLen];
            int bytesRead;

            do
            {
                // read a chunk of data from the input file
                bytesRead = fsIn.Read(buffer, 0, bufferLen);

                // Decrypt it
                cs.Write(buffer, 0, bytesRead);
            } while (bytesRead != 0);

            // close everything
            cs.Close(); // this will also close the unrelying fsOut stream
            fsIn.Close();
        }

        public static Dictionary<int, string> SplitCurrency(double money)
        {
            Dictionary<int, string> output = new Dictionary<int, string>();
            int count = 0;
            money = Math.Round(money);
            double temp = 0;
            while (money >= 1000)
            {
                temp = money % 1000;
                money = (money - temp) / 1000;
                output.Add(count, Convert.ToString(temp));
                count++;
            }
            output.Add(count, Convert.ToString(money));
            return output;
        }

        public static string GetString(int number)
        {
            switch (number)
            {
                case 0: return "đ";
                case 1: return "k";
                case 2: return "tr";
                case 3: return "tỷ";
                default: return "error";
            }
        }

        public static string FormatCurrency(double money)
        {
            Dictionary<int, string> result = SplitCurrency(money);
            if (result.Count >= 2)
            {
                return string.Format("{0}{1}{2}", result[result.Count - 1], GetString(result.Count - 1), ((result[result.Count - 2][0]) == '0') ? '\0' : (result[result.Count - 2][0]));
            }
            return string.Format("{0}{1}", result[result.Count - 1], GetString(result.Count - 1));
        }

        public static string GetFolderCoverUpload()
        {
            return "C:\\Website\\images.viecnho.com\\Cover\\";
        }

        public static string GetFolderAvatarUpload()
        {
            return "C:\\Website\\images.viecnho.com\\Avatar\\";
        }

        public static string GetFolderProvideUpload()
        {
            return "C:\\Website\\images.viecnho.com\\Provide\\";
        }

        public static string GetFolderBannerUpload()
        {
            return "C:\\Website\\images.viecnho.com\\Banner";
        }

        public static string GetImageCoverUpload()
        {
            return "http://images.viecnho.com/Cover/";
        }

        public static string GetImageAvatarUpload()
        {
            return "http://images.viecnho.com/Avatar/";
        }

        public static string GetImageProvideUpload()
        {
            return "http://images.viecnho.com/Provide/";
        }

        public static string GetImageBannerUpload()
        {
            return "http://images.viecnho.com/Banner/";
        }

        public static void ViecNhoSendMail(string to, string subject, string body)
        {
            SendMail("no-reply@viecnho.com", "ViecNho.com Thông báo.", to, subject, body, MailPriority.High);
        }

        public static void SendMail(string from, string displayfrom, string to, string subject, string body, MailPriority priority)
        {
            MailMessage msg = new MailMessage();

            // Your mail address and display name.
            // This what will appear on the From field.
            // If you used another credentials to access
            // the SMTP server, the mail message would be
            // sent from the mail specified in the From
            // field on behalf of the real sender.
            msg.From =
                new MailAddress(from, displayfrom);

            // To addresses
            msg.To.Add(to);
            //msg.To.Add(new MailAddress("friend_b@example.com", "Friend B"));

            // You can specify CC and BCC addresses also

            // Set to high priority
            msg.Priority = priority;

            msg.Subject = subject;
            msg.IsBodyHtml = true;
            // You can specify a plain text or HTML contents
            msg.Body = body;
            // In order for the mail client to interpret message
            // body correctly, we mark the body as HTML
            // because we set the body to HTML contents.

            // Attaching some data
            //msg.Attachments.Add(new Attachment("C:\\Site.lnk"));

            // Connecting to the server and configuring it
            SmtpClient client = new SmtpClient();
            client.Host = "smtp.mandrillapp.com";
            client.Port = 587;
            client.EnableSsl = true;
            // The server requires user's credentials
            // not the default credentials
            client.UseDefaultCredentials = false;
            // Provide your credentials
            client.Credentials = new System.Net.NetworkCredential("sm@viecnho.com", "_jRYnQmX1PH5aNaV4VyPbA");
            client.DeliveryMethod = SmtpDeliveryMethod.Network;

            // Use SendAsync to send the message asynchronously
            client.Send(msg);
        }

        public static String GetRandomString(int size)
        {
            Random _rng = new Random();
            string _chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
            char[] buffer = new char[size];

            for (int i = 0; i < size; i++)
            {
                buffer[i] = _chars[_rng.Next(_chars.Length)];
            }
            return new string(buffer);
        }

        public static VerifyAccount GetVerifyAccount(string VerifyStatus)
        {
            return new VerifyAccount(VerifyStatus, true);
        }

        public static bool CheckPhone(string phone)
        {
            RegexPhone Regex = new RegexPhone();
            return Regex.CheckPhone(phone);
        }

        public static List<Category> CategorysToTree(List<Category> source)
        {
            List<Category> output = new List<Category>();
            output.AddRange((from s in source
                             where s.ParentID == 0
                             orderby s.DisplayNumber ascending
                             select s).ToList());
            foreach (var item in output)
            {
                LoopLoadCategory(item, source);
            }
            return output;
        }

        public static void LoopLoadCategory(Category cate, List<Category> source)
        {
            cate.Childrens = (from c in source
                              where c.ParentID == cate.ID
                              orderby c.DisplayNumber ascending
                              select c).ToList();
            if (cate.Childrens.Count > 0)
            {
                foreach (var item in cate.Childrens)
                {
                    LoopLoadCategory(item, source);
                }
            }
        }

        public static void NotifyEmail(EmailFormat format, DictionaryFormat dic)
        {
            string to = dic.GetDictionary()["receiveremail"];
            EmailFactory factory = new EmailFactory(format);
            factory.DictionaryEmail = dic.GetDictionary();
            var body = factory.ReplaceBodyWithDictionary();
            var subject = factory.ReplaceSubjectWithDictionary();
            UserUtility.ViecNhoSendMail(to, subject, body);
        }
        public static string GetVerifiedEmail(User user)
        {
            VerifyAccount verify = new VerifyAccount(user.VerifyStatus, true);
            if (verify.GetStatusOfStep(VerifyAccount.STEP_EMAIL))
            {
                return user.Email;
            }
            else
            {
                if (string.IsNullOrWhiteSpace(user.FbEmail))
                {
                    return user.Email;
                }
                else
                {
                    return user.FbEmail;
                }
            }
        }

        public static string ShortString(string source, string expectlength)
        {
            var length = Convert.ToInt32(expectlength);
            if (source.Length > length)
            {
                return source.Substring(0, length) + "...";
            }
            return source;

        }

        public static string RemoveHtml(string source)
        {
            Regex regex = new Regex("<[^<>]*>");
            source = regex.Replace(source, " ");
            Regex regex2 = new Regex("&[^&;]*;");
            source = regex2.Replace(source, " ");
            return source;
        }
        public static string GenerateId()
        {
            long i = 1;
            foreach (byte b in Guid.NewGuid().ToByteArray())
            {
                i *= ((int)b + 1);
            }
            return string.Format("{0:x}", i - DateTime.Now.Ticks);
        }
        public static string HashCode(string str)
        {
            string rethash = "";
            try
            {
                System.Security.Cryptography.SHA1 hash = System.Security.Cryptography.SHA1.Create();
                System.Text.ASCIIEncoding encoder = new System.Text.ASCIIEncoding();
                byte[] combined = encoder.GetBytes(str);
                hash.ComputeHash(combined);
                rethash = Convert.ToBase64String(hash.Hash);
            }
            catch (Exception ex)
            {
                string strerr = "Error in HashCode : " + ex.Message;
            }
            return rethash;
        }
    }
}